
import uvicorn
from fastapi import FastAPI, Request, Body
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from Model.Sensor import *
from DAO.HDataDAO import *
from Utils import calculator
import datetime
import requests
from fastapi.middleware.cors import CORSMiddleware
from Model.Time import *
from Model.ChartSum import *
import re
from typing import Dict


app = FastAPI()

# 配置 CORS 中间件
origins = [  
   "*" 
    # 如果需要允许所有源，可以使用 "*" ，但出于安全考虑，不建议在生产环境中这样做  
    # "*"  
]  
 
app.add_middleware(  
    CORSMiddleware,  
    allow_origins=origins,  
    allow_credentials=True,  
    allow_methods=["*"],  
    allow_headers=["*"],  
)

limit_config_echarts = {
    "湿度":[
        {
            "gt": 45,
            "lte": 55,
            "color": "#00BFFF"
        },
        {
            "gt": 0,
            "lte": 45,
            "color": "red"
        },
        {
            "gt": 55,
            "lte": 100,
            "color": "red"
        }
    ],
    "温度":[
        {
            "gt": 14,
            "lte": 24,
            "color": "#66CD00"
        },
        {
            "gt": 0,
            "lte": 14,
            "color": "red"
        },

        {
            "gt": 24,
            "lte": 100,
            "color": "red"
        }
    ]
}

@app.get("/")
@calculator.time_calculator
def read_root():
    sdd = SensorDateDAO()
    response = sdd.get_last_day_data()
    return response

def find_min_humidity(data, key_value="humidityValue", positions=["东", "南", "西", "北"], floor="4F"):
    # max_humidity 实际为 min
    max_humidity = 100
    max_humidity_device_name = None
    if key_value == "湿度":
        key = "humidityValue"
    else:
        key = "temperatureValue"
    filtered_data = [item for item in data["data"] if item["device_name"][3] in positions and item["device_name"][:2] == floor]
    for item in filtered_data:
        value = float(item[key].replace("%", "").replace("℃", ""))
        if value < max_humidity:
            max_humidity = value
            max_humidity_device_name = item["device_name"]
    return max_humidity_device_name, max_humidity

def find_max_humidity(data, key_value="humidityValue", positions=["东", "南", "西", "北"], floor="4F"):
    max_humidity = -1
    max_humidity_device_name = None
    if key_value == "湿度":
        key = "humidityValue"
    else:
        key = "temperatureValue"
    filtered_data = [item for item in data["data"] if item["device_name"][3] in positions and item["device_name"][:2] == floor]
    for item in filtered_data:
        value = float(item[key].replace("%", "").replace("℃", ""))
        if value > max_humidity:
            max_humidity = value
            max_humidity_device_name = item["device_name"]
    return max_humidity_device_name, max_humidity


def find_average_data(data, key_value="humidityValue", positions=["东", "南", "西", "北"], floor="4F"):
    if key_value == "湿度":
        key = "humidityValue"
    else:
        key = "temperatureValue"
    filtered_data = [item for item in data["data"] if item["device_name"][3] in positions and item["device_name"][:2] == floor]
    sum_value = 0
    count = 0
    for item in filtered_data:
        value = float(item[key].replace("%", "").replace("℃", ""))
        sum_value += value
        count += 1
    return round(sum_value / count, 2) if count > 0 else 0


@app.get("/")
@calculator.time_calculator
def read_root():
    sdd = SensorDateDAO()
    response = sdd.get_last_day_data()
    return response


@app.post("/get_chart_sum")
@calculator.time_calculator
def get_chart_sum(req: dict):
    positions = req.get("positions")
    floor = req.get("floors")
    days = req.get("days")
    key = req.get("key")

    sdd = SensorDateDAO()
    data_list = sdd.get_rencent_data(days)
    data_list = [{"time": item["time"], "data": [d for d in item["data"] if d["device_name"][3] in positions and d["device_name"][:2] == floor]} for item in data_list]

    if key!= "全部":
        c_s = ChartSum()
        c_s.name = key
        if key == "湿度":
            c_s.danwei = "%"
            c_s.yAxisLabelFormatter = "{value} %"
            c_s.legend_data = ["湿度"]
            c_s.limitValue = 55
            c_s.limitValue2 = 45
        elif key == "温度":
            c_s.danwei = "℃"
            c_s.yAxisLabelFormatter = "{value} ℃"
            c_s.legend_data = ["温度"]
            c_s.limitValue = 24
            c_s.limitValue2 = 14
        c_s.title = Title(
            text=f"{floor} {key}  ({'、'.join(positions)})——最大值",
            subtext=f"{days}天数据展示",
        )
        c_s.visualMapPieces = limit_config_echarts[key]

        for data in data_list:
            device_name, m_num = find_max_humidity(data=data, key_value=key, positions=positions, floor=floor)
            time = data["time"]
            c_s.xAxisData.append(time.strftime('%Y-%m-%d %H:%M'))
            c_s.seriesData.append(m_num)
        c_s.min = min(
            max(int(min(c_s.seriesData)*0.95), (int(min(c_s.seriesData))-1)),
            c_s.limitValue-1
        )
        c_s.max = (
            min(int(max(c_s.seriesData)*1.05), int(max(c_s.seriesData))+1),
       
        )
        return {"chartData1": c_s, "chartData2": {}}
    else:
        c_s_1 = ChartSum()
        c_s_1.name = "温度"
        c_s_1.danwei = "℃"
        c_s_1.legend_data = ["温度", "湿度"]
        c_s_1.visualMapPieces = limit_config_echarts["温度"]
        c_s_1.limitValue = 24
        c_s_1.limitValue2 = 14
        c_s_1.title = Title(
            text=f"{floor} {key}  ({'、'.join(positions)})——最大值",
            subtext=f"{days}天数据展示",
        )

        c_s_2 = ChartSum()
        c_s_2.name = "湿度"
        c_s_2.danwei = "%"
        c_s_2.legend_data = ["温度", "湿度"]
        c_s_2.visualMapPieces = limit_config_echarts["湿度"]
        c_s_2.limitValue = 55
        c_s_2.limitValue2 = 45
        c_s_2.title = Title(
            text=f"{floor} {key}  ({'、'.join(positions)})——最大值",
            subtext=f"{days}天数据展示",
        )

        for data in data_list:
            device_name, temp_num = find_max_humidity(data=data, key_value="温度", positions=positions, floor=floor)
            time = data["time"]
            c_s_1.xAxisData.append(time.strftime('%Y-%m-%d %H:%M'))
            c_s_1.seriesData.append(temp_num)
            device_name, hum_num = find_max_humidity(data=data, key_value="湿度", positions=positions, floor=floor)
            c_s_2.xAxisData.append(time.strftime('%Y-%m-%d %H:%M'))
            c_s_2.seriesData.append(hum_num)

        c_s_1.min = min(
            max(int(min(c_s_1.seriesData)*0.95), (int(min(c_s_1.seriesData))-1)),
            c_s_1.limitValue-1
        )
        c_s_1.max = max(
            min(int(max(c_s_1.seriesData)*1.05), int(max(c_s_1.seriesData))+1),
            c_s_1.limitValue+1
        )
        c_s_2.min = min(
            max(int(min(c_s_2.seriesData)*0.95), (int(min(c_s_2.seriesData))-1)),
            c_s_2.limitValue-1
        )
        c_s_2.max = max(
            min(int(max(c_s_2.seriesData)*1.05), int(max(c_s_2.seriesData))+1),
            c_s_2.limitValue+1
        )
        return {"chartData1": c_s_1, "chartData2": c_s_2}



@app.post("/get_chart_sum_min")
@calculator.time_calculator
def get_chart_sum_min(req: dict):
    positions = req.get("positions")
    floor = req.get("floors")
    days = req.get("days")
    key = req.get("key")

    sdd = SensorDateDAO()
    data_list = sdd.get_rencent_data(days)
    data_list = [{"time": item["time"], "data": [d for d in item["data"] if d["device_name"][3] in positions and d["device_name"][:2] == floor]} for item in data_list]

    if key!= "全部":
        c_s = ChartSum()
        c_s.name = key
        if key == "湿度":
            c_s.danwei = "%"
            c_s.yAxisLabelFormatter = "{value} %"
            c_s.legend_data = ["湿度"]
            c_s.limitValue = 55
            c_s.limitValue2 = 45
        elif key == "温度":
            c_s.danwei = "℃"
            c_s.yAxisLabelFormatter = "{value} ℃"
            c_s.legend_data = ["温度"]
            c_s.limitValue = 24
            c_s.limitValue2 = 14
        c_s.title = Title(
            text=f"{floor} {key}  ({'、'.join(positions)})——最小值",
            subtext=f"{days}天数据展示",
        )
        c_s.visualMapPieces = limit_config_echarts[key]

        for data in data_list:
            device_name, m_num = find_min_humidity(data=data, key_value=key, positions=positions, floor=floor)
            time = data["time"]
            c_s.xAxisData.append(time.strftime('%Y-%m-%d %H:%M'))
            c_s.seriesData.append(m_num)
        c_s.min = (
            max(int(min(c_s.seriesData)*0.95), (int(min(c_s.seriesData))-1)),

        )
        c_s.max = (
            min(int(max(c_s.seriesData)*1.05), int(max(c_s.seriesData))+1),
        )
        return {"chartData1": c_s, "chartData2": {}}
    else:
        c_s_1 = ChartSum()
        c_s_1.name = "温度"
        c_s_1.danwei = "℃"
        c_s_1.legend_data = ["温度", "湿度"]
        c_s_1.visualMapPieces = limit_config_echarts["温度"]
        c_s_1.limitValue = 24
        c_s_1.limitValue2 = 14
        c_s_1.title = Title(
            text=f"{floor} {key}  ({'、'.join(positions)})——最小值",
            subtext=f"{days}天数据展示",
        )

        c_s_2 = ChartSum()
        c_s_2.name = "湿度"
        c_s_2.danwei = "%"
        c_s_2.legend_data = ["温度", "湿度"]
        c_s_2.visualMapPieces = limit_config_echarts["湿度"]
        c_s_2.limitValue = 55
        c_s_2.limitValue2 = 45
        c_s_2.title = Title(
            text=f"{floor} {key}  ({'、'.join(positions)})——最大值",
            subtext=f"{days}天数据展示",
        )

        for data in data_list:
            device_name, temp_num = find_min_humidity(data=data, key_value="温度", positions=positions, floor=floor)
            time = data["time"]
            c_s_1.xAxisData.append(time.strftime('%Y-%m-%d %H:%M'))
            c_s_1.seriesData.append(temp_num)
            device_name, hum_num = find_min_humidity(data=data, key_value="湿度", positions=positions, floor=floor)
            c_s_2.xAxisData.append(time.strftime('%Y-%m-%d %H:%M'))
            c_s_2.seriesData.append(hum_num)

        c_s_1.min = min(
            max(int(min(c_s_1.seriesData)*0.95), (int(min(c_s_1.seriesData))-1)),
            c_s_1.limitValue-1
        )
        c_s_1.max = max(
            min(int(max(c_s_1.seriesData)*1.05), int(max(c_s_1.seriesData))+1),
            c_s_1.limitValue+1
        )
        c_s_2.min = min(
            max(int(min(c_s_2.seriesData)*0.95), (int(min(c_s_2.seriesData))-1)),
            c_s_2.limitValue-1
        )
        c_s_2.max = max(
            min(int(max(c_s_2.seriesData)*1.05), int(max(c_s_2.seriesData))+1),
            c_s_2.limitValue+1
        )
        return {"chartData1": c_s_1, "chartData2": c_s_2}




@app.post("/get_chart_data_average")
@calculator.time_calculator
def get_chart_data_average(req: dict):
    positions = req.get("positions")
    floor = req.get("floors")
    days = req.get("days")
    key = req.get("key")

    sdd = SensorDateDAO()
    data_list = sdd.get_rencent_data(days)
    data_list = [{"time": item["time"], "data": [d for d in item["data"] if d["device_name"][3] in positions and d["device_name"][:2] == floor]} for item in data_list]

    if key!= "全部":
        c_s = ChartSum()
        c_s.name = key
        if key == "湿度":
            c_s.danwei = "%"
            c_s.yAxisLabelFormatter = "{value} %"
            c_s.legend_data = ["湿度"]
            c_s.limitValue = 55
            c_s.limitValue2 = 45
        elif key == "温度":
            c_s.danwei = "℃"
            c_s.yAxisLabelFormatter = "{value} ℃"
            c_s.legend_data = ["温度"]
            c_s.limitValue = 24
            c_s.limitValue2 = 14
        c_s.title = Title(
            text=f"{floor} {key}  ({'、'.join(positions)})——平均值",
            subtext=f"{days}天数据展示",
        )
        c_s.visualMapPieces = limit_config_echarts[key]

        for data in data_list:
            average_num = find_average_data(data=data, key_value=key, positions=positions, floor=floor)
            time = data["time"]
            c_s.xAxisData.append(time.strftime('%Y-%m-%d %H:%M'))
            c_s.seriesData.append(average_num)
        c_s.min = min(
            max(int(min(c_s.seriesData)*0.95), (int(min(c_s.seriesData))-1)),
            c_s.limitValue-1
        )
        c_s.max = (
            min(int(max(c_s.seriesData)*1.05), int(max(c_s.seriesData))+1),

        )
        return {"chartData1": c_s, "chartData2": {}}
    else:
        c_s_1 = ChartSum()
        c_s_1.name = "温度"
        c_s_1.danwei = "℃"
        c_s_1.legend_data = ["温度", "湿度"]
        c_s_1.visualMapPieces = limit_config_echarts["温度"]
        c_s_1.limitValue = 24
        c_s_1.limitValue2 = 14
        c_s_1.title = Title(
            text=f"{floor} {key}  ({'、'.join(positions)})——平均值",
            subtext=f"{days}天数据展示",
        )

        c_s_2 = ChartSum()
        c_s_2.name = "湿度"
        c_s_2.danwei = "%"
        c_s_2.legend_data = ["温度", "湿度"]
        c_s_2.visualMapPieces = limit_config_echarts["湿度"]
        c_s_2.limitValue = 55
        c_s_2.limitValue2 = 45
        c_s_2.title = Title(
            text=f"{floor} {key}  ({'、'.join(positions)})——平均值",
            subtext=f"{days}天数据展示",
        )

        for data in data_list:
            temp_num = find_average_data(data=data, key_value="温度", positions=positions, floor=floor)
            time = data["time"]
            c_s_1.xAxisData.append(time.strftime('%Y-%m-%d %H:%M'))
            c_s_1.seriesData.append(temp_num)
            hum_num = find_average_data(data=data, key_value="湿度", positions=positions, floor=floor)
            c_s_2.xAxisData.append(time.strftime('%Y-%m-%d %H:%M'))
            c_s_2.seriesData.append(hum_num)

        c_s_1.min = min(
            max(int(min(c_s_1.seriesData)*0.95), (int(min(c_s_1.seriesData))-1)),
            c_s_1.limitValue-1
        )
        c_s_1.max = max(
            min(int(max(c_s_1.seriesData)*1.05), int(max(c_s_1.seriesData))+1),
            c_s_1.limitValue+1
        )
        c_s_2.min = min(
            max(int(min(c_s_2.seriesData)*0.95), (int(min(c_s_2.seriesData))-1)),
            c_s_2.limitValue-1
        )
        c_s_2.max = max(
            min(int(max(c_s_2.seriesData)*1.05), int(max(c_s_2.seriesData))+1),
            c_s_2.limitValue+1
        )
        return {"chartData1": c_s_1, "chartData2": c_s_2}


@app.get("/get_last_3_day_data/{page_id}")
@calculator.time_calculator
def read_last_3_day_data(item_id: int):
    start_page = (item_id - 1) * 100 + 1
    end_page = item_id  * 100
    sdd = SensorDateDAO()
    response = sdd.get_last_day_data()
    return response

@app.get("/get_current_data")
@calculator.time_calculator
def get_current_data():
    sdd = SensorDateDAO()
    #res = sdd.get_current_data()
    data = get_data()['data']
   
    response = {
                "4F":{"东":[],"南":[],"西":[],"北":[],},
                "5F":{"东":[],"南":[],"西":[],"北":[],},
                "6F":{"东":[],"南":[],"西":[],"北":[],}
                }

    for item in data:
        
        if item['device_name'][:2] in response.keys() and item['device_name'][3] in "东南西北" :
            response[item['device_name'][:2]][item['device_name'][3]].append(item)
    return response

@app.post("/get_table_data_by_time")
@calculator.time_calculator
def get_table_data_by_time(item: dict):
    time_str = item.get("time")  

    sdd = SensorDateDAO()
    res = sdd.get_data_by_time(time_str)

    if res == None:
        return "No Data",404
    data = res['data']

    response = {
        "4F": {
            "东": [],
            "南": [],
            "西": [],
            "北": []
        },
        "5F": {
            "东": [],
            "南": [],
            "西": [],
            "北": []
        },
        "6F": {
            "东": [],
            "南": [],
            "西": [],
            "北": []
        }
    }

    for item in data:
        floor = item['device_name'][:2]
        direction = item['device_name'][3]
        if floor in response.keys() and direction in "东南西北":
            response[floor][direction].append(item)
    return {"data":response, "time":res['time']}

def get_data():
    url = "http://172.21.21.14:8103/prod-api/largeScreen/queryLargeScreenTemperatureAndHumidity?idcId=89313d16-2223-11ef-93ec-0242ac110005"
    headers = {
        "Cookie": "vue_admin_template_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6ImFkbWluQDEyMyIsInVzZXJuYW1lIjoiYWRtaW4ifQ.yILvN2N_XL_BmGPiwtN3HmrAXgOxaRLLhjO0fO8lp2k; JSESSIONID=BB854A12A9B949AC96916660DFA1D6FC; JSESSIONID=F915CF9F468D019A3F5774A235242FAD",
        "User-Agent": "apifox/1.0.0 (https://www.apifox.cn)",
        "Accept": "*/*",
        "Host": "172.21.21.14:8103",
        "Accept-Encoding": "gzip, deflate, br",
        "Connection": "keep-alive"
    }

    response = requests.post(url, headers=headers)
    data = response.json()
    return data

if __name__ == '__main__':
    uvicorn.run("app:app", host="0.0.0.0", port=8000, reload=True)